package com.coderman.infosys.auth.infrast.repositoryimpl;

import com.coderman.infosys.auth.domain.bo.system.MenuBO;
import com.coderman.infosys.auth.domain.bo.system.SystemBO;
import com.coderman.infosys.auth.domain.bo.system.ModuleBO;
import com.coderman.infosys.auth.domain.repository.SystemModuleRepository;
import com.coderman.infosys.auth.infrast.dao.dataobject.ModuleDO;
import com.coderman.infosys.auth.infrast.dao.mapper.ModuleMapper;
import com.coderman.infosys.auth.infrast.dao.dataobject.MenuDO;
import com.coderman.infosys.auth.infrast.dataconvert.ModuleConvert;
import com.coderman.infosys.auth.infrast.dataconvert.MenuConvert;
import com.coderman.infosys.auth.infrast.mq.producer.SystemMqProducer;
import com.coderman.infosys.auth.infrast.dataconvert.SystemConvert;
import com.coderman.infosys.auth.infrast.dao.mapper.SystemMapper;
import com.coderman.infosys.auth.infrast.dao.dataobject.SystemDO;
import com.coderman.infosys.auth.infrast.dao.mapper.MenuMapper;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @Description:接口实现类
 * @Author：
 * @CreateTime：2022-01-02 15:27:38
 * @version v1.0
 */
@Service
public class SystemModuleRepositoryImpl  implements SystemModuleRepository{

	private  Logger logger = LoggerFactory.getLogger(this.getClass());


    @Autowired
    private SystemMapper systemMapper;

    @Autowired
    private ModuleMapper moduleMapper;

    @Autowired
    private MenuMapper menuMapper;


    /**
     * 关于事务的问题，这里讨论一下，一般来说不在领域实现层进行事务控制，但是这里如果从
     * controller请求直接调用domain层，由于没有应用层参与所以如果需要事务控制就需要在领域层实现
     * 这里需要结合spring 事务的特性进行构建，如果业务比较复杂的话在adapter-controller之间构建一个应用服务也是可以的，
     * 所以需要酌情处理
     * @param systemBO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
	public Long registSystemMeta(SystemBO systemBO){
        SystemDO systemDO = SystemConvert.INSTANCE.bo2do(systemBO);

        //这个判断代表从这个方法进来的可能不仅仅是系统本身的信息持久化
        //还有模块菜单和按钮的持久化
        if(StringUtils.isNotEmpty(systemDO.getSystemCode())){
            //持久化系统
            systemMapper.insert(systemDO);
        }

        //持久化模块菜单
        if(CollectionUtils.isEmpty(systemBO.getModuleBOList())){
            return systemDO.getId();
        }


        //持久化模块菜单-->根据菜单编码判断是否需要持久化
        List<ModuleBO> moduleBOList = systemBO.getModuleBOList().stream().filter(moduleBO -> StringUtils.isNotEmpty(moduleBO.getModuleCode())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(moduleBOList)){
            return systemDO.getId();
        }
        List<ModuleDO> moduleDOList = ModuleConvert.INSTANCE.boList2doList(moduleBOList);
        moduleMapper.insertBatch(moduleDOList);


        //持久化按钮
        systemBO.getModuleBOList().stream().forEach(moduleBO -> {
            if(CollectionUtils.isNotEmpty(moduleBO.getMenuBOList())){
                List<MenuDO> menuDOList = MenuConvert.INSTANCE.boList2doList(moduleBO.getMenuBOList());
                menuMapper.insertBatch(menuDOList);
            }
        });

        //todo 发送事务持久化事件
        return systemDO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
	public Integer updateSystemMeta(SystemBO systemBO){
        SystemDO systemDO = SystemConvert.INSTANCE.bo2do(systemBO);
        //更新系统
        systemMapper.update(systemDO);

        //更新模块菜单
        if(CollectionUtils.isNotEmpty(systemBO.getModuleBOList())){
            List<ModuleDO> moduleDOList = ModuleConvert.INSTANCE.boList2doList(systemBO.getModuleBOList());
            for (ModuleDO moduleDO : moduleDOList){
                moduleMapper.update(moduleDO);
            }
        }

        //更新按钮
        if(CollectionUtils.isNotEmpty(systemBO.getModuleBOList())){
            systemBO.getModuleBOList().stream().forEach(moduleBO -> {
                List<MenuDO> menuDOList = MenuConvert.INSTANCE.boList2doList(moduleBO.getMenuBOList());
                for (MenuDO menuDO : menuDOList){
                    menuMapper.update(menuDO);
                }
            });
        }

        return 1;
    }

    @Override
    public SystemBO getBySystemCode(String systemCode) {
        SystemDO systemDO = systemMapper.getBySystemCode(systemCode);
        SystemBO systemBO = SystemConvert.INSTANCE.do2bo(systemDO);
        if(systemBO == null){
            //todo throw exception
        }
        //通过mapper构建聚合
        List<ModuleBO> moduleBOList = ModuleConvert.INSTANCE.doList2boList(moduleMapper.getBySystemCode(systemCode));
        systemBO.setModuleBOList(moduleBOList);
        for (ModuleBO moduleBO : moduleBOList){
            List<MenuBO> menuBOList = MenuConvert.INSTANCE.doList2boList(menuMapper.getListByModuleCode(moduleBO.getModuleCode()));
            moduleBO.setMenuBOList(menuBOList);
        }

        return systemBO;
    }

    @Override
    public ModuleBO getByModuleCode(String moduleCode) {
        return ModuleConvert.INSTANCE.do2bo(moduleMapper.getByModuleCode(moduleCode));
    }

    @Override
    public MenuBO getMenuBO(String menuCode) {
        return MenuConvert.INSTANCE.do2bo(menuMapper.getByMenuCode(menuCode));
    }

}